// 当前默认时间
const currenTime = {
  year: 2020,
  month: 4,
  day: 26,
  week: 7,
  hour: 13,
  minute: 23,
  second: 45
};

// 获取当月的天数
function getMonthDay(year, month) {
  const monthToDayMap = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
  if (year % 4 === 0 || year % 400 === 0) {
    monthToDayMap[1] = 29;
  }
  return monthToDayMap[month - 1];
}

// 创建DOM元素的通用函数
function createElementWithClass(tagName, className) {
  const element = document.createElement(tagName);
  element.className = className;
  return element;
}

// 创建时间单位DOM的通用函数
function createTimeUnitDOM(wrapperClass, count, start, unit, domArray) {
  const wrapper = createElementWithClass('div', wrapperClass);
  for (let i = start; i <= count; i++) {
    const span = document.createElement('span');
    span.innerText = `${i}${unit}`;
    wrapper.appendChild(span);
    domArray.push(span);
  }
  return wrapper;
}

// 当前罗盘时钟对象构造函数
function Clock(currenTime) {
  // 初始化时间属性
  this.currenYear = currenTime.year;
  this.currentMonth = currenTime.month;
  this.currentDay = currenTime.day;
  this.currentWeek = currenTime.week;
  this.currentHour = currenTime.hour;
  this.currentMinute = currenTime.minute;
  this.currentSecond = currenTime.second;
  this.monthToDays = getMonthDay(currenTime.year, currenTime.month);

  // 初始化DOM集合
  this.monthsDom = [];
  this.daysDom = [];
  this.weeksDom = [];
  this.hoursDom = [];
  this.minutesDom = [];
  this.secondsDom = [];
  this.weeks = ['一', '二', '三', '四', '五', '六', '日'];

  this.updateTimer = null;
  this.animationTimer = null;

  // 初始化DOM结构
  this.dom = this.createDom();
  this.init = function() { this.animate() };
}

// 创建罗盘时钟dom结构
Clock.prototype.createDom = function() {
  const dom = createElementWithClass('div', 'clock-box');

  // 创建年份DOM
  const yearDom = createElementWithClass('div', 'year');
  this.yearWrapper = yearDom;
  yearDom.innerText = `${this.currenYear}年`;

  // 创建月份DOM
  this.monthWrapper = createTimeUnitDOM('month', 12, 1, '月', this.monthsDom);

  // 创建日期DOM
  this.dayWrapper =
      createTimeUnitDOM('day', this.monthToDays, 1, '日', this.daysDom);

  // 创建星期DOM
  this.weekWrapper = createTimeUnitDOM('week', 7, 1, '星期', this.weeksDom);

  // 创建小时DOM
  this.hourWrapper = createTimeUnitDOM('hour', 23, 0, '时', this.hoursDom);

  // 创建分钟DOM
  this.minuteWrapper =
      createTimeUnitDOM('minute', 59, 0, '分', this.minutesDom);

  // 创建秒钟DOM
  this.secondWrapper =
      createTimeUnitDOM('second', 59, 0, '秒', this.secondsDom);

  // 将各时间单位DOM添加到主容器
  [yearDom, this.monthWrapper, this.dayWrapper, this.weekWrapper,
   this.hourWrapper, this.minuteWrapper, this.secondWrapper]
      .forEach(element => dom.appendChild(element));

  return dom;
};

// 优化后的animate方法
Clock.prototype.animate = function() {
  // 清除已有定时器
  if (this.updateTimer) clearInterval(this.updateTimer);
  if (this.animationTimer) clearTimeout(this.animationTimer);

  const animateUnit = (domArray, delay) => {
    setTimeout(() => {
      const deg = 360 / domArray.length;
      domArray.forEach((element, index) => {
        element.style.transform = `rotateZ(-${index * deg}deg)`;
      });
    }, delay);
  };

  // 使用数组存储动画单位及其延迟时间
  const animationUnits = [
    {dom: this.monthsDom, delay: 0},
    {dom: this.daysDom, delay: 1000},
    {dom: this.weeksDom, delay: 2000},
    {dom: this.hoursDom, delay: 2500},
    {dom: this.minutesDom, delay: 3500},
    {dom: this.secondsDom, delay: 4500}
  ];

  // 批量执行动画
  animationUnits.forEach(unit => animateUnit(unit.dom, unit.delay));

  // 更新当前时间并设置定时器
  setTimeout(() => {
    const updateTime = () => {
      const date = new Date();
      // 添加时间差补偿（单位：秒）
      const compensation = Math.round((Date.now() - this.lastUpdate) / 1000);
      if (compensation > 1) {
        date.setSeconds(date.getSeconds() + compensation);
      }
      this.currenYear = date.getFullYear();
      this.currentMonth = date.getMonth() + 1;
      this.currentDay = date.getDate();
      this.currentWeek = date.getDay();
      this.currentHour = date.getHours();
      this.currentMinute = date.getMinutes();
      this.currentSecond = date.getSeconds();

      // 使用对象存储旋转角度
      const rotations = {
        month: 360 / this.monthsDom.length,
        day: 360 / this.daysDom.length,
        week: 360 / 7,
        hour: 360 / 24,
        minute: 360 / 60,
        second: 360 / 60
      };

      // 批量更新时间单位和旋转角度
      this.yearWrapper.innerText = `${this.currenYear}年`;
      this.monthWrapper.style.transform =
          `rotate(${(this.currentMonth - 1) * rotations.month}deg)`;
      this.dayWrapper.style.transform =
          `rotate(${(this.currentDay - 1) * rotations.day}deg)`;
      this.weekWrapper.style.transform =
          `rotate(${(this.currentWeek - 1) * rotations.week}deg)`;
      this.hourWrapper.style.transform =
          `rotate(${this.currentHour * rotations.hour}deg)`;
      this.minuteWrapper.style.transform =
          `rotate(${this.currentMinute * rotations.minute}deg)`;
      this.secondWrapper.style.transform =
          `rotate(${this.currentSecond * rotations.second}deg)`;
    };

    setInterval(updateTime, 1000);
  }, 5500);
};

Clock.prototype.calibrateTime = function() {
  const date = new Date();
  this.currenYear = date.getFullYear();
  this.currentMonth = date.getMonth() + 1;
  this.currentDay = date.getDate();
  this.currentWeek = date.getDay() - 1;
  this.currentHour = date.getHours();
  this.currentMinute = date.getMinutes();
  this.currentSecond = date.getSeconds();
  this.monthToDays = getMonthDay(this.currenYear, this.currentMonth);

  // 更新DOM显示
  this.yearWrapper.innerText = `${this.currenYear}年`;
  this.monthWrapper.style.transform =
      `rotate(${(this.currentMonth - 1) * (360 / this.monthsDom.length)}deg)`;
  this.dayWrapper.style.transform =
      `rotate(${(this.currentDay - 1) * (360 / this.daysDom.length)}deg)`;
  this.weekWrapper.style.transform =
      `rotate(${this.currentWeek * (360 / 7)}deg)`;
  this.hourWrapper.style.transform =
      `rotate(${this.currentHour * (360 / 24)}deg)`;
  this.minuteWrapper.style.transform =
      `rotate(${this.currentMinute * (360 / 60)}deg)`;
  this.secondWrapper.style.transform =
      `rotate(${this.currentSecond * (360 / 60)}deg)`;
};

document.addEventListener('visibilitychange', () => {
  if (!document.hidden) {
    const timeDiff = Date.now() - this.lastUpdate;
    if (timeDiff > 2000) {
      c.calibrateTime();   // 校准时间
      c.animate();         // 强制重新初始化
      c.changeMonthDay();  // 更新月份天数
    }
  } else {
    this.lastUpdate = Date.now();
  }
});

Clock.prototype.changeMonthDay =
    function() {
  // 获取当前月对应的天数
  this.monthToDays = getMonthDay(this.currenYear, this.currentMonth);
  // 更新日期的dom集合
  this.daysDom = [];
  this.dayWrapper.innerHTML = '';
  var deg = 360 / this.monthToDays;
  for (var i = 1; i <= this.monthToDays; i++) {
    var oSpan = document.createElement('span');
    oSpan.innerText = i + '日';
    this.dayWrapper.appendChild(oSpan);
    oSpan.style.transform = 'rotateZ(-' + (i - 1) * deg + 'deg)';
    this.daysDom.push(oSpan);
  }
}

/*------------萤火虫特效实现-----------*/
let arr = [];
let app = document.getElementById("app");
let clientW = app.offsetWidth;
let clientH = app.offsetHeight;

// 确保 app 元素存在且可见
if (!app) {
  app = document.createElement("div");
  app.id = "app";
  document.body.appendChild(app);
}
app.style.position = 'absolute';
app.style.top = '0';
app.style.left = '0';
app.style.width = '100%';
app.style.height = '100%';
app.style.zIndex = '1000';  // 确保 app 元素在最上层

function addItem() {
  // 限制萤火虫的最大数量
  if (arr.length >= MAX_ELEMENTS) {
    return;
  }

  let div = document.createElement("div");
  const cName = (Math.floor(Math.random() * 3) + 1);
  div.setAttribute("class", "round" + (cName == 0 ? '' : cName));
  div.style.position = 'absolute';
  div.style.left = Math.floor(Math.random() * clientW) + "px";
  div.style.top = Math.floor(Math.random() * clientH) + "px";
  div.lifetime =
      Math.floor(Math.random() * 100) + 1000;  // 随机生成寿命，范围为1000到1100

  // 为每个萤火虫设置随机的速度和方向
  div.speed = Math.random() * 0.5 + 0.1;    // 随机速度
  div.angle = Math.random() * 2 * Math.PI;  // 随机角度


  // 设置随机的闪烁动画持续时间
  const randomBlinkDuration =
      Math.random() * 2 + 0.5;  // 随机持续时间在0.5到2.5秒之间
  div.style.animation = `blink ${randomBlinkDuration}s infinite`;

  // 设置随机的宽度和高度
  const randomSize = Math.random() * 10 + 1;  // 随机大小在1到10像素之间
  div.style.width = `${randomSize}px`;
  div.style.height = `${randomSize}px`;

  app.appendChild(div);
  arr.push(div);
}

const MAX_ELEMENTS = 300;

function move() {
  if (arr.length > MAX_ELEMENTS) {
    clearInterval(window.addTask);
    arr = arr.slice(-MAX_ELEMENTS);  // 保持最大数量限制
  }

  for (let i = arr.length - 1; i >= 0; i--) {
    const div = arr[i];
    const {offsetLeft: x, offsetTop: y} = div;

    // 边界处理：移除屏幕外元素
    if (x < -50 || x > clientW + 50 || y < -50 || y > clientH + 50) {
      div.remove();
      arr.splice(i, 1);
      continue;
    }

    // 递减寿命
    div.lifetime--;
    if (div.lifetime <= 0) {
      div.remove();
      arr.splice(i, 1);
      continue;
    }

    // 当寿命小于10时，开始渐隐效果
    if (div.lifetime < 10) {
      div.style.transition = 'opacity 0.5s';
      div.style.opacity = div.lifetime / 10;
    }

    // 随机调整萤火虫的方向和速度
    div.angle += (Math.random() - 0.5) * 0.2;   // 随机调整角度
    div.speed += (Math.random() - 0.5) * 0.05;  // 随机调整速度

    // 使用固定的速度和方向进行移动
    const dx = div.speed * Math.cos(div.angle);
    const dy = div.speed * Math.sin(div.angle);

    // 累加偏移量
    div.x = (div.x || 0) + dx;
    div.y = (div.y || 0) + dy;

    // 使用transform进行更平滑的移动
    div.style.transform = `translate(${div.x}px, ${div.y}px)`;
  }

  // 使用requestAnimationFrame实现平滑动画
  requestAnimationFrame(move);
}

// 使用requestAnimationFrame替代setInterval
function startAnimation() {
  requestAnimationFrame(move);
  setInterval(addItem, 50);
}

startAnimation();

var c = new Clock(currenTime);
var wrapper = document.getElementsByClassName('wrapper')[0];
wrapper.appendChild(c.dom);
c.init();
